/* terminal.c
 * This file is part of the Tisa Project.
 * 
 * Authors: Cleiber Marques da Silva <cleiber.dev@gmail.com>
 *          Odilson Tadeu Valle <odilson@sj.cefetsc.edu.br>
 *
 * Tisa Project is free software; you can redistribute
 * it and/or modify it under the terms of the GNU General Public
 * License as published by the Free Software Foundation; version 2 of
 * the License.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <readline/readline.h>
#include <readline/history.h>

#include "tisa.h"
#include "log.h"
#include "socket.h"

int done = 1;
/* The names of functions that actually do the manipulation. */
static int cmd_tref(char *arg, struct boiler *heater);
static int cmd_href(char *arg, struct boiler *heater);
static int cmd_help(char *arg, struct boiler *heater);
static int cmd_quit(char *arg, struct boiler *heater);

struct cmd commands[] = {
  { "tref", cmd_tref, "Change the temperature" },
  { "href", cmd_href, "Change the water level" },
  { "help", cmd_help, "Display this help screen" },
  { "quit", cmd_quit, "Quit using Tisa" },
  { (char *)NULL, NULL, (char *)NULL }
};

/* Forward declarations. */
static char *stripwhite(char *string);
static struct cmd *find_command(char *name);
static int execute_line(char *line, struct boiler *heater);

void terminal(struct boiler *heater)
{
	char *line, *s;

	fprintf(stdout, "Welcome to Tisa Project version %s\n", VERSION);

/* Loop reading and executing lines until the user quits. */
	while (done) {
		line = readline("Tisa> ");

		if (!line)
			break;

		/* Remove leading and trailing whitespace from the line.
		 * Then, if there is anything left, add it to the history list
		 * and execute it.
		 */
		s = stripwhite(line);

		if (*s) {
			add_history(s);
			execute_line(s, heater);
		}
		free(line);
	}
}

/* Execute a command line. */
static int execute_line(char *line, struct boiler *heater)
{
	int i = 0;
	char *word;
	struct cmd *command;

	/* Isolate the command word. */
	while (line[i] && whitespace(line[i]))
		i++;
	word = line + i;

	while (line[i] && !whitespace(line[i]))
		i++;

	if (line[i])
		line[i++] = '\0';

	command = find_command(word);

	if (!command) {
		fprintf(stderr, "%s: No such command for Tisa Project.\n", word);
		return -1;
	}

	/* Get argument to command, if any. */
	while (whitespace(line[i]))
		i++;

	word = line + i;

	/* Call the function. */
	return ((*(command->func)) (word, heater));
}

/* Look up NAME as the name of a command, and return a pointer to that
   command.  Return a NULL pointer if NAME isn't a command name. */
static struct cmd *find_command(char *name)
{
	int i;

	for (i = 0; commands[i].name; i++) {
		if (strcmp (name, commands[i].name) == 0)
		return (&commands[i]);
	}

	return ((struct cmd *)NULL);
}

/* Strip whitespace from the start and end of STRING.  Return a pointer
   into STRING. */
static char *stripwhite(char *string)
{
	register char *s, *t;

	for (s = string; whitespace(*s); s++);

	if (*s == 0)
		return s;

	t = s + strlen (s) - 1;
	while (t > s && whitespace(*t))
		t--;
	*++t = '\0';

	return s;
}

/* Tisa commands */
static int cmd_tref(char *arg, struct boiler *heater)
{
	if (!arg || !*arg) {
		fprintf(stdout, "Argument required!\n");
		return 0;
	}

/*	sprintf(msg, "ani%s", arg);
	send_msg(heater->sock_fd, heater->server, msg);
	recv_msg(heater->sock_fd, msg);
	if ((response_boiler("ani", msg)) < 0) {
		fprintf(stderr, "ani failed!\n");
		return 0;
	}*/

	pthread_mutex_lock(&heater->mutex);
	heater->variables[TREF] = atof(arg);
	pthread_mutex_unlock(&heater->mutex);

	log_print(LOG_NOTICE, "Change the temperature TRef = %s\n", arg);
	return 0;
}

static int cmd_href(char *arg, struct boiler *heater)
{
	if (!arg || !*arg) {
		fprintf(stdout, "Argument required!\n");
		return 0;
	}
	
	pthread_mutex_lock(&heater->mutex);
	heater->variables[HREF] = atof(arg);
	pthread_mutex_unlock(&heater->mutex);

	log_print(LOG_NOTICE, "Change the water level HRef = %s\n", arg);
	return 0;
}

/* Print out help for ARG, or for all of the commands if ARG is
   not present. */
static int cmd_help(char *arg, struct boiler *heater)
{
	int i;
	int printed = 0;

	for (i = 0; commands[i].name; i++) {
		if (!*arg || (strcmp (arg, commands[i].name) == 0)) {
			fprintf(stdout, "%s\t\t%s.\n", commands[i].name, commands[i].doc);
			printed++;
		}
	}

	if (!printed) {
		fprintf(stderr, "No commands match `%s'.  Possibilties are:\n", arg);

		for (i = 0; commands[i].name; i++) {
			/* Print in four columns. */
			if (printed == 4) {
				printed = 0;
				fprintf (stdout, "\n");
		}

			fprintf(stdout, "%s\t", commands[i].name);
			printed++;
		}

		if (printed)
			fprintf(stdout, "\n");
	}
	return 0;
}

/* The user wishes to quit using this program.  Just set DONE
   zero. */
static int cmd_quit(char *arg, struct boiler *heater)
{
	done = 0;
	return 0;
}
